using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.IO;
using System.Text.RegularExpressions;

namespace VisualizationPackage
{
    public class ColorMap
    {
        private List<ColorMapNode> _map = new List<ColorMapNode>();

        public List<ColorMapNode> Map
        {
            get { return _map; }
            set { _map = value; }
        }
        public Color this[double distribution]
        {
            get
            {
                int index = _map.IndexOf(new ColorMapNode(distribution));
                if (index != -1)
                    return _map[index].NodeColor;
                return Color.White;
            }
            set
            {
                if (_map.Contains(new ColorMapNode(distribution)))
                    _map[_map.IndexOf(new ColorMapNode(distribution))].NodeColor = value;
                else
                    _map.Add(new ColorMapNode(distribution, value));
            }
        }
        public static ColorMap Generate(double start, double end, int count)
        {
            ColorMap colorMap = new ColorMap();
            Color color = Color.FromArgb(0, 0, 255);
            int step = 0;
            try
            {
                step = 255 * 4 / (count - 4);
            }
            catch
            {
            }
            double vStep = (end - start) / count;
            if (step <= 0)
            {
                switch (count)
                {
                    case 2:
                        colorMap[start] = Color.Blue;
                        colorMap[end] = Color.Red;
                        break;
                    case 3:
                        colorMap[start] = Color.Blue;
                        colorMap[(start + end) / 2] = Color.FromArgb(0, 255, 255);
                        colorMap[end] = Color.Red;
                        break;
                    case 4:
                        colorMap[start] = Color.Blue;
                        colorMap[(start + end) / 3] = Color.FromArgb(0, 255, 255);
                        colorMap[(start + end) * 2 / 3] = Color.FromArgb(255, 255, 0);
                        colorMap[end] = Color.Red;
                        break;
                }
                return colorMap;
            }
            
            for (int i = 0; i < 255; i += step)
            {
                colorMap[start] = color;
                color = Color.FromArgb(color.R, i, color.B);
                start += vStep;
            }
            color = Color.FromArgb(color.R, 255, color.B);
            for (int i = 0; i < 255; i += step)
            {
                colorMap[start] = color;
                color = Color.FromArgb(color.R, color.G, 255 - i);
                start += vStep;
            }
            color = Color.FromArgb(color.R, color.G, 0);
            for (int i = 0; i < 255; i += step)
            {
                colorMap[start] = color;
                color = Color.FromArgb(i, color.G, color.B);
                start += vStep;
            }
            color = Color.FromArgb(255, color.G, color.B);
            for (int i = 0; i < 255; i += step)
            {
                colorMap[start] = color;
                color = Color.FromArgb(color.R, 255 - i, color.B);
                start += vStep;
            }
            colorMap[start] = Color.Red;
            //for (int i = 0; i < count; i++)
            //{
            //    colorMap[start] = color;
            //    color = Color.FromArgb(color.ToArgb() + step);
            //    start += vStep;
            //}
            return colorMap;
        }
        public static ColorMap Load(string filePath)
        {
            ColorMap colorMap = new ColorMap();
            StreamReader sr = new StreamReader(filePath);
            Regex regColorLine = new Regex(@"^\s*(?<value>[\d\-\.e\+]+)\s+(?<R>[\d\-\.e\+]+)\s+(?<G>[\d\-\.e\+]+)\s+(?<B>[\d\-\.e\+]+)", RegexOptions.IgnoreCase);
            Match m = regColorLine.Match(sr.ReadLine());
            string str;
            while (m.Success)
            {
                string value = m.Groups["value"].Value,
                    R = m.Groups["R"].Value,
                    G = m.Groups["G"].Value,
                    B = m.Groups["B"].Value;
                colorMap[double.Parse(value)] = Color.FromArgb(int.Parse(R), int.Parse(G), int.Parse(B));
                str = sr.ReadLine();
                if (str == null || str == "")
                    break;
                m = regColorLine.Match(str);
            }
            return colorMap;
        }
    }
    public class ColorMapNode
    {
        private double _value;
        private Color _nodeColor;

        public Color NodeColor
        {
            get { return _nodeColor; }
            set { _nodeColor = value; }
        }
        public double Value
        {
            get { return _value; }
            set { _value = value; }
        }
        public ColorMapNode(double value, Color color)
        {
            Value = value;
            NodeColor = color;
        }
        public ColorMapNode(double value)
        {
            Value = value;
        }
        public override bool Equals(object obj)
        {
            return (obj as ColorMapNode).Value == Value;
        }
    }
}
